package com.quicks.beauty.server.web;

import com.quicks.beauty.core.dao.UserPointAccountMapper;
import com.quicks.beauty.core.entity.UserAccountDetail;
import com.quicks.beauty.core.entity.UserInvite;
import com.quicks.beauty.core.entity.UserOrder;
import com.quicks.beauty.core.entity.UserPointAccount;
import com.quicks.beauty.core.entity.WxUser;
import com.quicks.beauty.core.utils.UUIDGenerator;
import com.quicks.beauty.server.common.MD5Util;
import com.quicks.beauty.server.config.WXConfig;
import com.quicks.beauty.server.service.OrderService;
import com.quicks.beauty.server.service.RedisBillService;
import com.quicks.beauty.server.service.UserService;
import com.quicks.beauty.server.vos.WXPayResult;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.security.auth.message.callback.PrivateKeyCallback;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;


@RestController
@RequestMapping(value = "km/")
public class AsyncNotifyController {
    private static Logger logger = LoggerFactory.getLogger(AsyncNotifyController.class);

    @Autowired
    private OrderService orderService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    WXConfig wxConfig;

    @Autowired
    private RedisBillService redisBillService;
    @Autowired
    private UserService userService;
    @Autowired
    @Qualifier(value = "redisTemplate")
    private RedisTemplate<String,Object> redisTemplate;


    @ApiOperation(value = "微信支付通知回调")
    @RequestMapping(value = "/wxPayCallback/{orderNo}", method = {RequestMethod.POST, RequestMethod.GET})
    public void paySuccessCallback(@PathVariable(value = "orderNo") String orderCode, HttpServletRequest request, HttpServletResponse response) throws Exception {
        InputStream inputStream = request.getInputStream();
        String postData = IOUtils.toString(inputStream, "UTF-8");
        logger.info("微信支付,请求回调,回调数据为:" + postData);

        UserOrder userOrder = orderService.getUserOrderByCodes(orderCode);

        if (userOrder == null) {
            return;
        }


        XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));
        //将请求返回的内容通过xStream转换为UnifiedOrderRespose对象
        xStream.alias("xml", WXPayResult.class);
        Object obj = xStream.fromXML(postData);
        WXPayResult payResult = new WXPayResult();
        BeanUtils.copyProperties(obj, payResult);

        if (payResult != null && payResult.getReturn_code().equals("SUCCESS")) {
            SortedMap<String, Object> treeMap = new TreeMap<>();
            treeMap.put("appid", wxConfig.getAppId());
            treeMap.put("bank_type", payResult.getBank_type());
            treeMap.put("cash_fee", payResult.getCash_fee());
            treeMap.put("fee_type", payResult.getFee_type());
            treeMap.put("is_subscribe", payResult.getIs_subscribe());
            treeMap.put("mch_id", wxConfig.getMerchantId());
            treeMap.put("nonce_str", payResult.getNonce_str());
            treeMap.put("openid", payResult.getOpenid());
            treeMap.put("out_trade_no", payResult.getOut_trade_no());
            treeMap.put("result_code", payResult.getResult_code());
            treeMap.put("return_code", payResult.getReturn_code());
            treeMap.put("time_end", payResult.getTime_end());
            treeMap.put("total_fee", payResult.getTotal_fee());
            treeMap.put("trade_type", payResult.getTrade_type());
            treeMap.put("transaction_id", payResult.getTransaction_id());

            StringBuffer sb = new StringBuffer();
            Set es = treeMap.entrySet();//字典序
            Iterator it = es.iterator();
            while (it.hasNext()) {
                Map.Entry entry = (Map.Entry) it.next();
                String v = (String) entry.getValue();
                String k = (String) entry.getKey();
                //为空不参与签名、参数名区分大小写
                if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                    sb.append(k + "=" + v + "&");
                }
            }
            sb.append("key=" + wxConfig.getApiKey());
            logger.info("二次签名是" + sb.toString());
            String paySign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
            logger.info("paySign:{}", paySign);
            if (paySign.equals(payResult.getSign())) {

                Integer status = userOrder.getTradeState();
                if (status.equals(Integer.valueOf(1))) {
                    String result_code = payResult.getResult_code();
                    if ("SUCCESS".equals(result_code.trim())) {
                        String success = success();
                        PrintWriter out = response.getWriter();
                        orderService.asyncHandleOrder(userOrder.getId(), true);
                        out.print(success);
                        out.close();
                    }
                } else if (status.equals(Integer.valueOf(0))) {  // 待支付状态
                    String result_code = payResult.getResult_code();
                    if ("SUCCESS".equals(result_code.trim())) {
/*                        int count  = orderService.findOrderPay(userOrder.getUserId());
                        if(count >0){

                        }else{
                            String fromId =orderService.getUserInvite(userOrder.getUserId());
                            if(fromId!=null&&!"".equals(fromId)){
                                WxUser wxUser = userService.getUserById(userOrder.getUserId());
                                UserPointAccount fromUserAccount = userService.getUserPoint(fromId);
                                Integer fromUserOldPoints = fromUserAccount.getPoints();
                                UserAccountDetail fromUserAccountDetail = new UserAccountDetail();
                                Date date = new Date();
                                int mp =userOrder.getMoney().multiply(BigDecimal.TEN).intValue();
                                int pp = userOrder.getPoints();
                                int pointsss = mp+pp;
                                fromUserAccountDetail.setId(UUIDGenerator.generate()).setCreateTime(date).setAccountId(fromUserAccount.getId())
                                        .setKinds(0).setPoints(pointsss/2)
                                        .setRemark("好友("+wxUser.getNickName()+")首次消费赠送").setStates(0).setUserId(fromId); // TODO 首次送积分,一半
                                fromUserAccountDetail.setSurplusPoints(fromUserOldPoints+ fromUserAccountDetail.getPoints());
                                fromUserAccount.setPoints(fromUserOldPoints+ fromUserAccountDetail.getPoints());
                                fromUserAccount.setUpdateTime(date);
                                orderService.updateAccount(fromUserAccount);
                                orderService.insertAccountDetail(fromUserAccountDetail);
                            }
                        }*/

                        String success = success();
                        PrintWriter out = response.getWriter();
                        out.print(success);
                        out.close();
                        redisBillService.pushUserOrderById(userOrder.getUserId(), userOrder.getId());
                        redisTemplate.delete(userOrder.getId()+"&"+userOrder.getUserId());
                       orderService.asyncHandleOrder(userOrder.getId(), true);
                    } else if ("FAIL".equals(result_code.trim())) {
                       orderService.asyncHandleOrder(userOrder.getId(), false);
                    }
                } else if (status.equals(Integer.valueOf(5))) { // 支付失败
                    String result_code = payResult.getResult_code();
                    if ("SUCCESS".equals(result_code.trim())) {
                        String success = success();
                        PrintWriter out = response.getWriter();
                        out.print(success);
                        out.close();
                    } else if ("FAIL".equals(result_code.trim())) {
                        orderService.asyncHandleOrder(userOrder.getId(), false);
                    }
                }

            } else { // 微信校验失败
                logger.info("微信校验签名失败,请执行后续操作");
                logger.info("微信校验签名失败,回调数据为:" + postData);
            }
        } else {
            logger.info("系统校验签名失败,回调数据为:" + postData);
        }
        stringRedisTemplate.delete(userOrder.getId());
        logger.info("删除过期的订单Id:,{}",userOrder.getId());

    }


    private String success() {
        StringBuilder builder = new StringBuilder();
        builder.append("<xml>");
        builder.append("<return_msg><![CDATA[OK]]></return_msg>");
        builder.append("<return_code><![CDATA[SUCCESS]]></return_code>");
        builder.append("</xml>");
        return builder.toString();
    }
}
